Skip to content

Release 1.3.0 — federation read surfaces (governance_read.v1 + Plainweave) + the 1.3.0 line#21

Open
tachyon-beep wants to merge 34 commits into
mainfrom
release/1.3.0-federation-reads
Open

Release 1.3.0 — federation read surfaces (governance_read.v1 + Plainweave) + the 1.3.0 line#21
tachyon-beep wants to merge 34 commits into
mainfrom
release/1.3.0-federation-reads

Conversation

@tachyon-beep

Copy link
Copy Markdown
Collaborator

Release 1.3.0 — the unpushed federation/security line + two new federation read surfaces

Folds the complete unpushed main delta (31 commits) into the 1.3.0 release. pyproject + __version__ are both at 1.3.0; CHANGELOG.md [1.3.0] is updated to match.

Headline — new federation read surfaces

  • governance_read.v1 — legis publishes a per-SEI governance read for Warpline (PDR-0007). New surface on CLI (legis governance-read <sei>), MCP (governance_read tool) and HTTP (GET /governance/sei/{sei:path}/governance-read), returning the frozen governance_read.v1 envelope (contract: contracts/governance_read.v1.schema.json). A pure projection of the forge-proof per-SEI attestation read into a cleared-only posture shape (operator_overrideprotected_override, signoff_clearedoperator_signoff), so Warpline's reverify_worklist(include_federation=True) can enrich advisorily. Fail-closed throughout: unverifiable trail → discriminated status:"unavailable" (never silent []); tampered trail fails loud on all three transports (HTTP 500 / MCP AUDIT_INTEGRITY_FAILURE / CLI nonzero); records:[] under checked is honest absence of clearance, never "ungoverned"/"unknown SEI". Advisory-only — Warpline echoes enrichment.governance and never gates (GV-LG-1). Ships the producer half the prior 1.3.0 conformance note flagged as unwired.

  • Plainweave preflight — advisory consumer (PDR-0008). First sibling consumer of Plainweave's weft.plainweave.preflight_facts.v1; mirrors the Warpline advisory-preflight read (PlainweaveMcpClient + StdioMcpInvoke, fail-closed → unavailable, GV-LG-3 validated, PLAINWEAVE_MCP_CMD). Enrich-only; verdicts byte-identical with/without Plainweave.

Also in 1.3.0 (already on the line)

  • Security: posture read_floor() fails closed on a chain-integrity break (legis-476ab6f125); protected-cell batches advance the HeadAnchor (legis-0c310712a7).
  • Changed: Warpline advisory preflight rebuilt onto Warpline's real MCP wire — WARPLINE_API_URLWARPLINE_MCP_CMD (legis-a53d92507d).
  • Added: nested .weft/legis/.gitignore at install; the legis-resident halves of six cross-repo Weft seam conformance oracles.

Verification (local, CI-equivalent)

  • pytest: 1378 passed, 9 skipped · mypy: clean (80 files) · ruff: clean
  • coverage 92.48% (floor 88); all per-package floors hold (service 95.0, mcp, api, warpline_preflight 95.3, new plainweave_preflight)
  • SEI oracle ✅ · policy-boundary-check PASS · governance-gate PASS_WITH_NOTICE
  • governance_read.v1 was hardened by a 7-agent review (a Critical CLI false-green caught + fixed) and the CLI chain-integrity guard is mutation-proven (neutering verify_integrity() reproduces the false-green; the regression test catches it).

Notes for the reviewer / merger

  • Integration tails are sibling-side, not legis-blocked: Warpline wires LegisGovernanceClient.governance_for_sei (the governance_read.v1 consumer); Plainweave's oracle golden is constructed, with live e2e capture a flagged follow-up.
  • Merging + tagging v1.3.0 triggers release.yml → PyPI (tag must equal pyproject 1.3.0 ✓; the live-Loomweave conformance gate is skip-not-fail absent LOOMWEAVE_URL).
  • Dependabot flags 3 vulnerabilities on the default branch (1 high, 2 low) — pre-existing, not introduced here (tracked separately: cryptography lower-bound, legis-ea02d6c6a8).
  • Follow-up: legis-a0e286f5aa (MCP outputSchema looser than the frozen contract — Minor).

🤖 Generated with Claude Code

tachyon-beep and others added 30 commits June 26, 2026 15:40
read_floor() now gates on verify_integrity() before returning the floor, so
a raw-DB-written/forged tail record that breaks the keyless hash chain can no
longer silently set the routing floor (it maps to the fail-closed structured
default). Cryptographic operator_sig verification stays the operator-side
doctor check (KEY_RESET-acknowledgment path only); a recomputed-chain forgery
remains the conceded raw-file-write residual (README.md:137).

Retires test_read_floor_uses_tail_read's 'must not call read_all' premise (the
integrity gate supersedes it) and corrects the now-false module docstring.

Closes the load-bearing half of legis-476ab6f125 (PRD-0005 criterion 1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
read_floor's keyless integrity gate cannot detect a file-write attacker who
recomputes the keyless chain; on a non-rekeyed ledger that is caught by neither
the hot read nor doctor (doctor's operator_sig check is the KEY_RESET-ack path
only). It is the conceded raw-file-write residual (README.md:137). This
characterization test makes the limit visible in the suite so it is never
implied-closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…→Plainweave refs

Adds/normalizes the 'not-for-X' Banner naming this member's specific misuse (deconfliction-first, not security/compliance); fixes hardcoded Charter→Plainweave prose. Re-vendored kit; build green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A protected record appended inside a batch defers its HeadAnchor advance
(the mid-batch head read is forbidden, Q-M5) and, unlike SignoffGate, had no
transaction owner to re-advance it after commit — so a batched protected
append could leave the anchor at the pre-batch head and a later tail-truncation
would go undetected. Add ProtectedGate.transaction(), a verbatim mirror of
SignoffGate.transaction(), as that owner.

Closes legis-0c310712a7 (PRD-0005 criterion 2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A protected append inside a raw store.transaction() (bypassing gate.transaction())
leaves the anchor stale — the supported safe path is gate.transaction(). This
characterization test makes the parity limit visible so it is never implied-closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Final-review cleanups (M1 unused Verdict import; M2 rank-5 comment landed inside
the _truncate_to docstring). No logic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r injectable invoke seam

Rewrites the warpline preflight client from an HTTP layer to a lightweight
MCP-envelope consumer. Deletes HttpWarplineClient and all urllib/http.client/
ipaddress helpers; adds WarplineMcpClient with an injectable Invoke seam for
offline testing. Validates schema, ok, meta (isinstance guard closes GV-LG-3
non-dict escape), local_only, peer_side_effects, and data.completeness —
every contract fault fails closed to WarplineError. Envelope is passed through
verbatim (bare-object MCP output schema makes pass-through lossless).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds StdioMcpInvoke — the production Invoke: a one-shot stdio JSON-RPC call
to warpline-mcp. shell=False + list argv; text=False byte-bounded stdout;
empty-argv rejected; entire post-spawn parse wrapped so every fault (spawn,
timeout, non-JSON, scalar result, isError, oversize) → WarplineError (fail
closed). Adds _read_jsonrpc_result for line-by-line id-matched response
scanning. Adds test_stdio_invoke.py (11 tests: fake server round-trip, live
transcript replay DoD gate, 5 fault parametrize, missing binary, empty argv,
timeout, oversize). Live-capture gate (warpline-mcp 1.2.0): exits on
stdin-EOF (rc=0), no interleaved I/O required, protocolVersion 2025-03-26,
structuredContent dict returned — subprocess.run one-shot confirmed safe.
notifications/initialized → id:null error, correctly ignored (id != 2).
Fixture warpline-mcp-live-session.jsonl is the verbatim 3-line capture.
Concern flagged (not fixed): warpline_impact_radius_get requires a "repo"
arg that WarplineMcpClient._call does not yet supply.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fix cross-task import breaks

Replace WARPLINE_API_URL/HttpWarplineClient with WARPLINE_MCP_CMD/WarplineMcpClient
in build_runtime; supply repo=str(project_root()) from the established cwd-anchored
resolver. Add required repo: str param to WarplineMcpClient.__init__ and thread it
into _call arguments (live capture proved warpline_impact_radius_get/-reverify_worklist_get
require "repo"; without it JSON-RPC -32602 kills the seam). Update all 9 test_client.py
construction sites to pass repo="/tmp/r" and tighten the argument-shape assertion.
Fix the three test_server.py tests that referenced the deleted HttpWarplineClient
and WARPLINE_API_URL. After this commit: mypy src/legis is clean, pytest collects
1285 tests with only test_warpline_preflight_oracle.py failing (Task 4's scope).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ular oracle; reverse producer obligation

Replace the hand-rolled flat golden with real warpline.impact_radius.v1 /
warpline.reverify_worklist.v1 envelopes live-captured from warpline-mcp 1.2.0
(legis repo, HEAD~1..HEAD, 2026-06-27).  Add machine-readable provenance marker
(_provenance.source = "live-captured") with a CI-visible test that fails if
"pending-live-capture" is committed without the escape env var.

Rewrite the oracle: deleted HttpWarplineClient/_decode_json_response imports
removed; all assertions now flow the golden through WarplineMcpClient._call
(schema/ok/meta/completeness validation is real), asserting HARDCODED literals
(schema=="warpline.impact_radius.v1", completeness=="NO_SNAPSHOT", affected==[],
meta.local_only==True, etc.) — never a re-parse of the golden.  Layer-2 recheck
repointed from the obsolete REST path to the MCP contract fixture path.

PROVENANCE.md: delete the "WARPLINE PRODUCER-SIDE OBLIGATION" block; record
legis as consumer of warpline's extant envelope per SEAM 4 §4A + GV-LG-3.

Re-pin GOLDEN_BLOB_SHA = 777b858.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…shaped envelopes + GV-LG-3 positive test

Replace all flat {affected/entries, count} warpline fakes with envelopes carrying
schema/ok/data.completeness/meta so the advisory payload (hostile values in
data.affected/data.items), not a contract violation, is what's proven inert.

test_warpline_advisory_boundary.py:
- _HostileWarpline now returns real-shaped envelopes with GV-LG-3-valid meta
  (local_only:true, peer_side_effects:[]) and hostile advisory payload (SEI="EVERYTHING").
- Add guard in byte-identity test: assert hostile side reached status=="checked"
  (side assertion, outside the compared blobs) so vacuous unavailable==unavailable
  cannot silently pass the test.
- Add test_gv_lg_3_invalid_meta_peer_side_effects_yields_unavailable: routes
  through WarplineMcpClient with peer_side_effects=["some-peer"] and asserts
  the end-to-end result is status=="unavailable".
- Structural boundary test (lines 143-174, derived from _TOOL_HANDLERS) preserved unchanged.

test_output_schema_conformance.py:
- _FakeWarpline returns real-shaped envelopes with valid meta (the old flat stubs
  would have been refused → unavailable, silently flipping status to unavailable
  and making the checked assertion vacuous).

test_server.py + test_preflight.py:
- All remaining flat warpline fakes updated to real-shaped envelopes;
  assertions updated to match (pass-through semantics preserved).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Measured coverage is 91.9% (79/86 statements covered in client.py).
Floor set at 88% to lock in the gain from the MCP-client rewrite
while leaving headroom for incidental churn.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… content-fallback test

IMPORTANT #1: add warpline-mcp-reverify-session.jsonl — three-line JSON-RPC
transcript of a real warpline_reverify_worklist_get call (warpline-mcp 1.2.0,
2026-06-27, legis repo, HEAD~1..HEAD).  Adds test_replays_a_REAL_reverify_session
that echoes these bytes through StdioMcpInvoke and asserts schema/completeness/
items from the capture.  Golden's reverify_worklist was already byte-identical
to the freshly captured structuredContent; GOLDEN_BLOB_SHA unchanged.
Updates PROVENANCE.md to document both halves are now live-captured with
committed transcripts.

MINOR (b): make text=False explicit in StdioMcpInvoke's subprocess.run call
(was implicit via the absence of text=True; explicit kwarg prevents a future
refactor from silently switching to char mode).

MINOR (c): add test_content_text_fallback_parse — exercises the content[0].text
parse path in StdioMcpInvoke when structuredContent is absent from the result.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… ship warpline preflight MCP-envelope fix; PDR-0005, PDR-0006

- PDR-0005: accept legis-476ab6f125 + legis-0c310712a7 against PRD-0005 (north-star 3->1; legis-0186c23a2c remains)
- PDR-0006: warpline preflight conforms to warpline's extant MCP envelope (transport=MCP, owner-confirmed); producer-obligation reversed; reverify kept droppable pending wardline
- refresh metrics.md (north-star 1; advisory-boundary re-proven; live-Loomweave gate -> skip-not-fail; coverage 92.25%), roadmap.md (Now 2/3 done), current-state.md
- includes the 3 codebase-validated implementation plans + review history

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… the warpline producer-obligation framing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…; sync uv.lock to 1.3.0

Plan for the warpline→legis governance read seam, revised against the 7-agent
ultracode review (CHANGES_REQUESTED → all 8 must-fixes folded in). Contract
artifacts (schema + warpline prompt) staged uncommitted for the build's Task 1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Commits the FROZEN governance_read.v1 contract: the discriminated-union
JSON schema (contracts/governance_read.v1.schema.json), the warpline
hand-off prompt (docs/contracts/warpline-governance-read.v1-prompt.md),
and the pinning test suite (tests/contract/test_governance_read_v1_schema.py).

Tests cover 3 positives, 3 discriminator-negatives, 8 constraint-negatives,
1 format test (with load-bearing rfc3339-validator assertion), and 1 drift
guard (structural equality of prompt's embedded schema block vs committed
file, stripping non-validating descriptions only).

Adds jsonschema[format] to the dev group so Draft202012Validator
format_checker enforces the RFC3339 date-time constraint on as_of.
.v1 is a ONE-WAY DOOR — any change to validation logic requires .v2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… helper

Adds the per-SEI governance-clearance projection (`read_governance_for_sei`),
the CLI/batch verified-gate wrapper (`read_governance_for_sei_gate` — mirrors
`evaluate_override_rate_gate` so both verify halves are mandatory), and the
shared unavailable-envelope helper (`governance_read_unavailable`) to
`service/governance.py`. Exports all three from `service/__init__.py`.
Includes `_POSTURE_BY_KIND` and `_is_rfc3339`; unknown-kind / bad-as_of
records are omitted (asymmetric-error), not fabricated. TDD red→green:
10 tests in `tests/service/test_governance_read.py`, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… projection)

Adds the `governance_read` MCP tool that exposes per-SEI verified governance
clearances as the `governance_read.v1` envelope, completing the warpline seam
for advisory governance enrichment. Key properties:

- BOTH-objects fail-closed pre-gate (mirrors attestation_get): gates on
  BOTH runtime.protected_gate AND runtime.trail_verifier; missing either ->
  status:"unavailable" (discriminated), never silent checked/[].
- Handler calls read_governance_for_sei(_governance_trail_records(runtime))
  which runs BOTH verify_integrity (chain) AND TrailVerifier.verify (sigs)
  via the verified_records path; tampered trail -> AUDIT_INTEGRITY_FAILURE.
- outputSchema built via _one_of over the v1 clearance_record fields
  (sei/disposition/posture/authority/as_of/reasons/content_hash), NOT
  attestation_get's fields.
- Registered in _AGENT_TOOLS, tool_definitions(), and _TOOL_HANDLERS.

Tests:
- tests/mcp/test_governance_read_tool.py: handler tests (checked/unavailable/
  tamper) incl. BOTH-objects gate on each missing half.
- tests/mcp/test_output_schema_conformance.py: two explicit variant cases
  (checked + unavailable) validate against the declared _one_of outputSchema.
- tests/conformance/test_governance_read_oracle.py: FROZEN GOLDEN mirroring
  test_warpline_attestation_oracle.py; byte-pinned blob SHA + LIVE==FROZEN
  value assert (not schema.validate); both clearance kinds pinned; content_hash
  cross-check confirms same records as the attestation golden.
- tests/conformance/fixtures/legis-governance-read.golden.json: committed golden
  (blob SHA 898fd1a).
- tests/mcp/test_server.py: update hard-coded tool list to include governance_read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exposes the governance_read.v1 per-SEI clearance read on the HTTP adapter
(Task 4). The route gates on BOTH protected_gate and trail_verifier (fail-closed
pre-gate identical to the MCP tool); verified_governance_records() runs both
chain and signature checks, mapping tamper to HTTP 500. Missing either object
yields a discriminated status:unavailable envelope, never a silent checked/[].
{sei:path} captures slash-bearing SEIs correctly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…te test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exposes per-SEI verified governance clearances (governance_read.v1) at the CLI
boundary. Both verification halves are mandatory per Constraint 1: verify_integrity()
(hash-chain/seq-contiguity/delete-reorder defence) runs FIRST, then
read_governance_for_sei_gate (signature half via the service layer). Omitting
either half is a false-green — test_cli_governance_read_chain_tamper_exits_nonzero
is RED without verify_integrity() and GREEN with it (mutation-verified).

Fail-closed: no LEGIS_HMAC_KEY → unavailable; missing DB → unavailable; chain
tamper → exit 1 + "audit integrity" stderr; signature tamper (key mismatch) → exit 1.
No bare except. No --json flag (output is always JSON). No duplicate governance
logic in the adapter — all decisions flow through service/governance.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…" contract

All tamper paths (chain gap AND signature mismatch) now emit the "audit
integrity" substring on stderr, matching the established contract used by
`service/governance.py:verified_records`, `mcp.py`, and the chain-tamper
path already in the same CLI helper. Fixes case (d) in the test, which
previously asserted "verification failed" (a substring only of the service
gate's AuditIntegrityError message, not the contract marker).

Change: `_governance_read` except block now prints
`"Error: audit integrity: {exc}"` instead of `"Error: {exc}"`, so the
"audit integrity" substring is present regardless of which verification
half raised. Test case (d) assertion updated from `"verification failed"`
to `"audit integrity"`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tructural check

Adds read_governance_for_sei, read_governance_for_sei_gate, and
governance_read_unavailable to the explicit warpline-free symbol list in
test_runtime_warpline_referenced_in_no_verdict_path_function, so any
future accidental warpline reference in these service functions is caught
immediately. Full CI-equivalent sweep passes: coverage 92.39%/all per-
package floors hold; ruff/mypy clean; SEI oracle, policy-boundary-check,
governance-gate all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ance_read.v1

Adds three test_cross_transport_* tests to the contract freeze file, each
capturing a REAL output from one transport adapter (MCP golden / HTTP
TestClient / CLI main()) and validating it against the committed frozen
contracts/governance_read.v1.schema.json with the rfc3339 format checker
wired. Satisfies Task 6 DoD item: one captured output per transport validates
against the frozen v1 schema. All 19 contract tests pass; per-package coverage
floors and all CI gates remain green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ctural, not byte)

The embedded schema block is an abridged structural mirror — every validating
keyword is identical to the canonical contracts/governance_read.v1.schema.json
(legis CI asserts it), but description annotations live only in the canonical
file. Prior "byte-equal" wording was inaccurate. Prose-only; the drift guard
test is unchanged and still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y at 1.3.0)

src/legis/__init__.py carried a stale __version__ = "1.2.0" from the 1.3.0-prep
that bumped pyproject.toml and CHANGELOG but not the constant, so `legis
--version` reported 1.2.0 on the 1.3.0 line. Surfaced when deploying the
local-main build for the warpline governance_read handshake.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ibling

Lands Plainweave in Legis's API: a read-only consumer of Plainweave's only
implemented producer, plainweave_preflight_facts_get / envelope
weft.plainweave.preflight_facts.v1 (ADR-006), which had no sibling consumer
and had never been exercised end-to-end.

Mirrors the existing warpline advisory-preflight read EXACTLY:
- legis/plainweave_preflight/client.py — injectable PlainweaveMcpClient +
  StdioMcpInvoke; every contract fault fails CLOSED -> PlainweaveError. The
  GV-LG-3 boundary is validated against Plainweave's real envelope shape
  (data.authority_boundary.{local_only, live_peer_calls, governance_verdicts}
  + mandatory data.freshness/facts), since Plainweave's meta carries no
  local_only/peer_side_effects (those are warpline's).
- service/preflight.read_plainweave_preflight — discriminated checked/unavailable
  SIBLING of read_warpline_preflight; None/fault -> unavailable with a reason,
  NEVER INTERNAL_ERROR, NEVER an empty-as-clean.
- mcp.py — plainweave_preflight_get tool next to warpline_preflight_get (separate
  advisory sibling, not merged); runtime.plainweave wired from PLAINWEAVE_MCP_CMD,
  default None -> unavailable; governance unaffected when absent/unconfigured.

ADVISORY ONLY, enrich-only: this read never changes a Legis policy/governance
decision. Tests pin it: a byte-identity test proves a hostile Plainweave client
cannot perturb a real verdict; a structural test proves no verdict-path function
references runtime.plainweave; a GV-LG-3 test refuses any producer claiming
governance_verdicts; the honest-degrade path (absent -> unavailable; ok:false
error envelope -> unavailable) is pinned.

Conformance oracle drives legis's real parser over a frozen golden built from the
producer contract (CONSTRUCTED, not live-captured — the hub session's MCP wiring
misroutes Plainweave; live end-to-end capture is a flagged follow-up in a
legis-rooted session). Gates green: ruff, mypy, pytest (1377 passed),
per-package coverage floors (plainweave_preflight 96.6%), sei oracle,
policy-boundary-check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tachyon-beep and others added 2 commits June 28, 2026 00:15
…tion pending) + record Plainweave consumer; PDR-0007, PDR-0008

Checkpoint 2026-06-28. PDR-0007 (build governance_read.v1, cleared-only per-SEI
read legis publishes for warpline, owner-directed) and PDR-0008 (record the
parallel session's Plainweave advisory consumer under federation-read doctrine).
North-star unchanged at 1 (federation work is seam-quality, not P2 findings).
Escalation: the push/publish release decision for the now-substantial unpushed
local main (G1 + Plainweave + 1.3.0 line) remains owner-gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….3.0

Records the two federation read surfaces added since the 1.3.0 section was
written (PDR-0007 governance_read.v1 producer; PDR-0008 Plainweave advisory
consumer) and updates the conformance note: the per-SEI governance read Warpline
needs is now shipped on legis's producer side. Owner-directed: fold into 1.3.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cee85267e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/legis/mcp.py
if not argv:
raise WarplineError("WARPLINE_MCP_CMD is blank")
from legis.config import project_root
warpline = WarplineMcpClient(invoke=StdioMcpInvoke(command=argv), repo=str(project_root()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the configured source root for Warpline

When the MCP server is launched from outside the target repo and LEGIS_SOURCE_ROOT points at the checkout (the same setting used for runtime.source_root and the other git/source tools), this constructs the Warpline client with project_root(), which is just the process cwd. warpline_preflight_get will then send Warpline a repo for the wrong checkout and return advisory impact/worklist data for that directory instead of the configured repository; build this from the same source root used later on the runtime.

Useful? React with 👍 / 👎.

raise WarplineError(f"{tool} envelope meta is {type(meta).__name__}, expected an object")
if meta.get("local_only") is not True:
raise WarplineError(f"{tool} meta.local_only is not true: {meta.get('local_only')!r}")
if meta.get("peer_side_effects"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require explicit no-side-effect metadata

When Warpline omits meta.peer_side_effects or returns it as null/false, this truthiness check accepts the envelope as checked, even though the GV-LG-3 boundary only proves safety when the producer explicitly says there were no peer side effects. A malformed boundary envelope should degrade through read_warpline_preflight to unavailable, not be passed through as advisory data; require the exact valid empty value before accepting it.

Useful? React with 👍 / 👎.

Comment on lines +109 to +110
proc = subprocess.run(self._command, input=stdin, capture_output=True,
timeout=self._timeout, shell=False, check=False, text=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail closed on non-zero MCP subprocess exits

If the configured warpline-mcp command writes a valid id=2 result and then exits non-zero, for example because a wrapper or the server crashes during shutdown, this check=False path has no later returncode guard and will still return structuredContent as a successful checked advisory result. The transport contract treats non-zero exit as a fault that should become WarplineError/unavailable, so check proc.returncode before accepting any parsed envelope.

Useful? React with 👍 / 👎.

tachyon-beep and others added 2 commits June 28, 2026 14:18
The renderer (render_text) appends an audience tag ("[operator]",
"[auto-fixable]", "[fixed]") to every check line. Five operator-key
check messages in doctor.py already ended with a literal " [operator]",
causing the renderer to emit "[operator] [operator]" double-tags.

Remove the trailing " [operator]" from the four message strings in
check_posture_key_reset and check_operator_key_accessible; the renderer
continues to own the audience tag on every check line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 1.3.0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c1d8e5c34

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +149 to +150
if isinstance(sc, dict):
return sc

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail closed on failed Plainweave subprocess exits

If PLAINWEAVE_MCP_CMD points to a wrapper/server that emits a valid id=2 structuredContent result and then exits non-zero (for example, a crash or failed cleanup during shutdown), this branch returns the envelope as successful checked advisory facts because proc.returncode is only included in later error strings and is never checked. That treats a failed MCP transport as success; check the return code before accepting structuredContent/content so read_plainweave_preflight degrades to unavailable.

Useful? React with 👍 / 👎.

Comment thread src/legis/mcp.py
if not argv:
raise PlainweaveError("PLAINWEAVE_MCP_CMD is blank")
from legis.config import project_root
plainweave = PlainweaveMcpClient(invoke=PlainweaveStdioMcpInvoke(command=argv), repo=str(project_root()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run Plainweave from the configured source root

When the MCP server is launched outside the target checkout with LEGIS_SOURCE_ROOT pointing at the repo, this still starts the Plainweave client with an invoker that inherits the process cwd; the repo=str(project_root()) value here is just cwd and is not sent by PlainweaveMcpClient anyway. Because the Plainweave producer roots itself from the launched command's working directory, plainweave_preflight_get can return facts for the wrong project instead of the configured source root; pass the configured source root through as the subprocess cwd (or equivalent) when wiring this client.

Useful? React with 👍 / 👎.

Comment on lines +367 to +368
datetime.fromisoformat(value.replace("Z", "+00:00"))
return True

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-RFC3339 governance timestamps

For signed records whose recorded_at is date-only or lacks an offset, datetime.fromisoformat still succeeds, so governance_read.v1 emits that value as as_of even though the frozen contract declares format: date-time and the docstring says malformed timestamps are omitted. A legacy/imported or test-injected signed clearance with recorded_at: "2026-06-02" or "2026-06-02T12:00:00" will therefore produce a checked envelope that fails the published schema instead of being safely omitted.

Useful? React with 👍 / 👎.

f"{tool} authority_boundary.governance_verdicts is not false: "
f"{boundary.get('governance_verdicts')!r}"
)
if "freshness" not in data or "facts" not in data: # degraded -> unavailable, not bare empty 'checked'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate Plainweave fact field types

This only checks that freshness and facts keys are present, so a malformed success envelope such as {"freshness": null, "facts": "not-a-list"} still returns status: "checked" and is passed through to callers as advisory facts. Since the Plainweave consumer contract says payload shape mismatches must degrade to unavailable, require the expected types (at least string freshness and array facts) before accepting the envelope.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant